<?php

namespace app\checkin\controller;

use app\checkin\model\ExchangeRecord as ExchangeModel;
use app\checkin\model\Member as MemberModel;
use app\checkin\model\Gift as GiftModel;
use app\checkin\model\PointsRecord as PointsModel;
use think\admin\helper\QueryHelper;
use think\facade\Db;

/**
 * 兑换记录管理
 * @class Exchange
 * @package app\checkin\controller
 */
class Exchange extends Base
{
    /**
     * 临时存储会员信息（用于表单提交后处理）
     * @var mixed
     */
    protected $tempMember;

    /**
     * 临时存储礼品信息
     * @var mixed
     */
    protected $tempGift;

    /**
     * 临时存储积分
     * @var int
     */
    protected $tempPoints;

    /**
     * 临时存储库存
     * @var int
     */
    protected $tempStock;

    /**
     * 临时存储门店ID
     * @var int
     */
    protected $tempStoreId;

    /**
     * 兑换记录列表
     * @auth true
     * @menu true
     */
    public function index()
    {
        $this->title = '兑换记录';
        ExchangeModel::mQuery()->layTable(function () {
            $this->assign('stores', $this->getAccessibleStores());
        }, function (QueryHelper $query) {
            // 礼品名搜索（精准匹配）
            $giftName = trim($this->request->get('gift_name', ''));
            if ($giftName !== '') {
                $query->where('gift_name', $giftName);
            }

            // 会员姓名搜索（精准匹配）
            $memberName = trim($this->request->get('member_name', ''));
            if ($memberName !== '') {
                $query->whereIn('member_id', function($q) use ($memberName) {
                    $q->table(MemberModel::mk()->getTable())
                      ->where('name', $memberName)
                      ->field('id');
                });
            }

            // 手机号搜索（精准匹配）
            $memberPhone = trim($this->request->get('member_phone', ''));
            if ($memberPhone !== '') {
                $query->whereIn('member_id', function($q) use ($memberPhone) {
                    $q->table(MemberModel::mk()->getTable())
                      ->where('phone', $memberPhone)
                      ->field('id');
                });
            }

            // 门店、操作员、时间范围搜索
            $query->equal('store_id,operator_id')->dateBetween('create_time');

            // 数据权限：非总账号显示本店记录 + 与本店有关系会员的所有跨店记录
            if (!$this->isMaster) {
                $relTable = \app\checkin\model\MemberStore::mk()->getTable();
                $sid = $this->storeId;
                $query->where(function ($q) use ($relTable, $sid) {
                    $q->where(['store_id' => $sid])
                      ->whereOrRaw("member_id IN (SELECT member_id FROM {$relTable} WHERE store_id = :sid)", ['sid' => $sid]);
                });
            }
            // 关联显示
            $query->with([
                'member',  // 关联会员信息
                'store',   // 关联门店信息
                'operator' // 关联操作员信息
            ]);
            // 倒序显示（最新的记录在前）
            $query->order('id desc');
        });
    }

    /**
     * 新增兑换
     * @auth true
     */
    public function add()
    {
        $this->title = '新增兑换';
        $this->_applyFormToken();
        ExchangeModel::mForm('form');
    }

    /**
     * 表单过滤
     * @param array $data
     */
    protected function _form_filter(array &$data)
    {
        if ($this->request->isGet()) {
            // 下拉数据
            $gifts = GiftModel::mk()->where(['status' => 1])->order('sort desc,id desc')->select()->toArray();
            $this->assign('gifts', $gifts);
            $this->assign('stores', $this->getAccessibleStores());
        } else {
            // 解析会员
            $key = trim($data['member_key'] ?? '');
            if ($key === '') $this->error('请输入会员卡号或手机号！');
            $member = MemberModel::mk()->where(function($q) use ($key){
                $q->where(['card_no' => $key])->whereOr(['phone' => $key]);
            })->findOrEmpty();
            if ($member->isEmpty()) $this->error('未找到对应会员！');
            if (intval($member->getAttr('status')) !== 1) $this->error('该会员已禁用，无法兑换！');

            // 解析礼品
            $giftId = intval($data['gift_id'] ?? 0);
            $gift = GiftModel::mk()->where(['id' => $giftId])->findOrEmpty();
            if ($gift->isEmpty()) $this->error('礼品不存在！');
            if (intval($gift->getAttr('status')) !== 1) $this->error('礼品未上架，无法兑换！');
            $points = intval($gift->getAttr('points_required'));
            $stock = intval($gift->getAttr('stock'));
            if ($stock !== -1 && $stock < 1) $this->error('礼品库存不足！');

            // 门店
            $storeId = $this->isMaster ? intval($data['store_id'] ?? 0) : $this->storeId;
            if (!$this->isMaster) $data['store_id'] = $storeId;
            if ($storeId < 1) $this->error('请选择兑换门店！');
            if (!$this->checkStorePermission($storeId)) $this->error('无权限操作该门店！');

            // 积分校验
            $available = intval($member->getAttr('available_points'));
            if ($available < $points) $this->error('会员可用积分不足！');

            // 组装写入字段
            $data['member_id'] = intval($member->getAttr('id'));
            $data['gift_id'] = $giftId;
            $data['gift_name'] = strval($gift->getAttr('name'));
            $data['points'] = $points;
            $data['operator_id'] = intval($this->user['id'] ?? 0);

            // 将会员、礼品、库存等信息存储到临时变量，供 _form_result 使用
            $this->tempMember = $member;
            $this->tempGift = $gift;
            $this->tempPoints = $points;
            $this->tempStock = $stock;
            $this->tempStoreId = $storeId;
        }
    }

    /**
     * 表单结果处理
     * @param bool $result
     */
    protected function _form_result(bool $result)
    {
        if ($result && $this->request->isPost()) {
            // 获取刚插入的兑换记录ID
            $exchangeId = ExchangeModel::mk()->getLastInsID();

            // 事务处理：扣积分、改库存与会员积分
            Db::transaction(function () use ($exchangeId) {
                $member = $this->tempMember;
                $gift = $this->tempGift;
                $points = $this->tempPoints;
                $stock = $this->tempStock;
                $storeId = $this->tempStoreId;

                // 扣减积分明细
                PointsModel::mk()->save([
                    'member_id'  => $member->getAttr('id'),
                    'store_id'   => $storeId,
                    'points'     => -$points,
                    'type'       => 2,
                    'source'     => 'exchange',
                    'related_id' => $exchangeId,
                    'status'     => 1,
                    'remark'     => '礼品兑换：' . $gift->getAttr('name'),
                    'operator_id'=> intval($this->user['id'] ?? 0),
                ]);

                // 更新会员积分
                MemberModel::mk()->where(['id' => $member->getAttr('id')])->update([
                    'used_points'      => intval($member->getAttr('used_points')) + $points,
                    'available_points' => intval($member->getAttr('available_points')) - $points,
                ]);

                // 减库存（不限库存 -1 不处理）
                if ($stock !== -1) {
                    $aff = GiftModel::mk()->where([['id', '=', $gift->getAttr('id')], ['stock', '>=', 1]])->dec('stock')->update();
                    if ($aff < 1) throw new \Exception('礼品库存不足或已变化，请重试！');
                }
            });

            // 兑换成功后，更新Redis缓存中的会员积分（如果存在的话）
            $memberId = intval($this->tempMember->getAttr('id'));
            $this->updateMemberCacheAfterExchange($memberId);

            $this->success('兑换成功！');
        }
    }

    /**
     * 兑换成功后更新Redis缓存中的会员积分
     * 从数据库重新查询最新的会员数据，然后更新Redis缓存
     * @param int $memberId 会员ID
     */
    private function updateMemberCacheAfterExchange(int $memberId)
    {
        try {
            // 从数据库重新查询最新的会员数据（事务已提交，数据已更新）
            $member = MemberModel::mk()->where(['id' => $memberId])->findOrEmpty();
            if ($member->isEmpty()) {
                return;
            }

            // 获取Redis连接
            $redis = new \Redis();
            $redisConfig = config('cache.stores.redis');
            if (!$redisConfig) {
                // 如果没有配置，尝试从.env读取
                $redisConfig = [
                    'host' => env('REDIS_HOST', '127.0.0.1'),
                    'port' => env('REDIS_PORT', 6379),
                    'password' => env('REDIS_PASSWORD', ''),
                    'database' => env('REDIS_DATABASE', 0),
                ];
            }

            $redis->connect($redisConfig['host'] ?? '127.0.0.1', $redisConfig['port'] ?? 6379, 2);
            if (!empty($redisConfig['password'])) {
                $redis->auth($redisConfig['password']);
            }
            $redis->select($redisConfig['database'] ?? 0);

            $cacheKey = "member:{$memberId}";

            // 检查缓存是否存在
            if ($redis->exists($cacheKey)) {
                // 获取缓存数据
                $cacheData = json_decode($redis->get($cacheKey), true);
                if ($cacheData && is_array($cacheData)) {
                    // 更新缓存中的积分信息为最新的数据库值
                    $cacheData['available_points'] = intval($member->getAttr('available_points'));
                    $cacheData['total_points'] = intval($member->getAttr('total_points'));

                    // 重新保存到Redis（保持原有TTL）
                    $ttl = $redis->ttl($cacheKey);
                    if ($ttl > 0) {
                        $redis->setex($cacheKey, $ttl, json_encode($cacheData, JSON_UNESCAPED_UNICODE));
                    }
                }
            }

            $redis->close();
        } catch (\Throwable $e) {
            // Redis更新失败不影响业务流程，只记录日志
            \think\facade\Log::warning("Failed to update member cache after exchange: " . $e->getMessage());
        }
    }

    /**
     * 删除记录
     * @auth true
     */
    public function remove()
    {
        ExchangeModel::mDelete();
    }
}
